/*
 * Copyright (c) 2025 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import 'package:flutter/cupertino.dart';

import 'immersion_rules.dart';

class AdaptiveImmersion {
  AdaptiveImmersion._internal();

  factory AdaptiveImmersion() => _instance;
  static final AdaptiveImmersion _instance = AdaptiveImmersion._internal();
  final double defaultVideoAspectRatio = 9 / 16;

  ImmersionInfo getImmersionInfo(
      BuildContext context, Size videoSize, double bottomTabHeight) {
    assert(videoSize.width >= 0 && videoSize.height >= 0,
        'videoSize must be non-negative');
    assert(bottomTabHeight >= 0, 'bottomTabHeight must be non-negative');
    MediaQueryData? mediaQueryData = MediaQuery.maybeOf(context);
    if (mediaQueryData == null) {
      throw FlutterError(
          'AdaptiveImmersion: context does not contain MediaQuery. Make sure you are calling this within a widget tree that has MediaQuery.');
    }
    double videoAspectRatio = safeDivide(videoSize.width, videoSize.height);
    Size windowSize = mediaQueryData.size;
    double windowAspectRatio = safeDivide(windowSize.width, windowSize.height);
    double topStatusBarHeight = mediaQueryData.padding.top;
    if (_isMatchVerticalVideo(videoAspectRatio, defaultVideoAspectRatio)) {
      ImmersionRule rule = immersionRules.firstWhere((ImmersionRule rule) {
        return rule.windowWidthRange.contains(windowSize.width) &&
            rule.windowRatioRange.contains(windowAspectRatio);
      });
      return rule.getImmersionInfo(
          videoAspectRatio, windowSize, bottomTabHeight, topStatusBarHeight);
    }
    return defaultImmersionRule.getImmersionInfo(
        videoAspectRatio, windowSize, bottomTabHeight, topStatusBarHeight);
  }

  bool _isMatchVerticalVideo(double videoAspectRatio, double matchAspectRatio,
      {double tolerance = 1e-6}) {
    return (videoAspectRatio - matchAspectRatio).abs() < tolerance;
  }
}

class ImmersionInfo {
  final Size videoSize;
  final Offset videoPosition;
  final ImmersionSetting immersionSetting;

  ImmersionInfo(
      {required this.videoSize,
      required this.videoPosition,
      required this.immersionSetting});

  @override
  String toString() {
    return 'ImmersionInfo{videoSize: $videoSize, videoPosition: '
        '$videoPosition, immersionSetting: ${immersionSetting.toString()}}';
  }
}

class ImmersionSetting {
  final bool isStatusBarImmersive;
  final bool isBottomTabImmersive;

  ImmersionSetting(
      {required this.isStatusBarImmersive, required this.isBottomTabImmersive});

  @override
  String toString() {
    return 'isStatusBarImmersive: $isStatusBarImmersive, isBottomTabImmersive: '
        '$isBottomTabImmersive';
  }
}
